package com.chenwc.amazons3;

import com.chenwc.common.util.Util;
import org.junit.jupiter.api.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.model.BucketVersioningStatus;
import software.amazon.awssdk.services.s3.model.ObjectVersion;

import java.io.File;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * @author chenwc
 */
public class AwszonS3Test {

    private static final Logger logger = LoggerFactory.getLogger(AwszonS3Test.class);

    private static final String BUCKET_NAME = "test";

    @BeforeAll
    public static void getMinioClient() {
        AwsUtil.getS3Client("http://192.168.100.129:9000",
                "6ABaREo6aw7dLp9jXfpc",
                "ASqAwPLxWs2rHC9fWH9jUQBtoIVf9NH3sVRM2MxR",
                Region.CN_NORTH_1);
    }

    @AfterAll
    public static void disconnect() {
        AwsUtil.close();
        AwsUtil.closeAsync();
        // 退出，这一步必须得加，不然用到异步的S3AsyncClient不会自动关闭
        System.exit(0);
    }

    @Test
    @Tag("bucket")
    @DisplayName("判断bucket是否存在")
    public void testBucketExists() {
        logger.info("bucket: {} Exists: {}", BUCKET_NAME, AwsUtil.bucketExists(BUCKET_NAME));
    }

    @Test
    @Tag("bucket")
    @DisplayName("createBucket")
    public void createBucket() {
        AwsUtil.createBucket(BUCKET_NAME);
        AwsUtil.setBucketVersioning(BUCKET_NAME, BucketVersioningStatus.ENABLED);
    }

    @Test
    @Tag("bucket")
    @DisplayName("listBucket")
    public void listBucket() {
        AwsUtil.listBucket();
    }

    @Test
    @Tag("bucket")
    @DisplayName("deleteObjectsInBucket")
    public void deleteObjectsInBucket() {
        AwsUtil.deleteObjectsInBucket(BUCKET_NAME);
    }

    @Test
    @Tag("bucket")
    @DisplayName("uploadObject")
    public void uploadObject() {
        File file = new File("D:\\Downloads\\highlight.js-11.9.0.tar.gz");
        String key = file.getName();
        boolean isUploadSuccessful = AwsUtil.uploadObject(BUCKET_NAME, key, file);
        logger.info("uploadObject: {}", isUploadSuccessful);
    }

    @Test
    @Tag("bucket")
    @DisplayName("multipartUploadObject")
    public void multipartUploadObject() {
        File file = new File("D:\\Downloads\\s3-api.pdf");
        String key = file.getName();
        boolean isMultipartUploadSuccessful = AwsUtil.multipartUploadObject(BUCKET_NAME, key, file);
        logger.info("multipartUploadObject: {}", isMultipartUploadSuccessful);
    }

    @Test
    @Tag("bucket")
    @DisplayName("downloadObject")
    public void downloadObject() {
        String key = "s3-api.pdf";
        boolean isDownloadSuccessful = AwsUtil.downloadObject(BUCKET_NAME, key, "D:\\Downloads\\s3-api.pdf");
        logger.info("downloadObject: {}", isDownloadSuccessful);
    }

    @Test
    @Tag("bucket")
    @DisplayName("downloadObjectByBytes")
    public void downloadObjectByBytes() {
        String key = "s3-api.pdf";
        boolean isDownloadSuccessful = AwsUtil.downloadObjectByBytes(BUCKET_NAME, key, "D:\\Downloads\\s3-api.pdf");
        logger.info("downloadObject: {}", isDownloadSuccessful);
    }

    @Test
    @Tag("bucket")
    @DisplayName("deleteObject")
    public void deleteObject() {
        String key = "s3-api.pdf";
        boolean isDeleteSuccessful = AwsUtil.deleteObject(BUCKET_NAME, key, "");
        logger.info("deleteObject: {}", isDeleteSuccessful);
    }

    @Test
    @Tag("bucket")
    @DisplayName("listBucketObjects")
    public void listBucketObjects() {
        AwsUtil.listBucketObjects(BUCKET_NAME);
    }

    @Test
    @Tag("bucket")
    @DisplayName("getObjectTags")
    public void getObjectTags() {
        String key = "s3-api.pdf";
        List<software.amazon.awssdk.services.s3.model.Tag> tagSet = AwsUtil.getObjectTags(BUCKET_NAME, key);
        if (tagSet != null && !tagSet.isEmpty()) {
            tagSet.forEach(tag -> logger.info("key: {}, value: {}", tag.key(), tag.value()));
        }
        else {
            logger.info("tagSet is Empty");
        }
    }

    @Test
    @Tag("bucket")
    @DisplayName("getObjectUrl")
    public void getObjectUrl() {
        String key = "s3-api.pdf";
        String url = AwsUtil.getObjectUrl(BUCKET_NAME, key);
        logger.info("url: {}", url);
    }

    @Test
    @Tag("bucket")
    @DisplayName("getObjectPresignedUrl")
    public void getObjectPresignedUrl() {
        String key = "s3-api.pdf";
        String url = AwsUtil.getObjectPresignedUrl(BUCKET_NAME, key);
        logger.info("url: {}", url);
    }

    @Test
    @Tag("bucket")
    @DisplayName("isObjectExist")
    public void isObjectExist() {
        String key = "s3-api.pdf";
        boolean isObjectExist = AwsUtil.isObjectExist(BUCKET_NAME, key);
        logger.info("isObjectExist: {}", isObjectExist);
    }

    @Test
    @Tag("bucket")
    @DisplayName("copyBucketObject")
    public void copyBucketObject() {
        String key = "s3-api.pdf";
        AwsUtil.copyBucketObject(BUCKET_NAME, key, BUCKET_NAME, "test/"+key);
    }

    @Test
    @Tag("bucket")
    @DisplayName("multipartUploadWithTransferManager")
    public void multipartUploadWithTransferManager() {
        File file = new File("D:\\Downloads\\ideaIU-2023.3.6.exe");
        String key = file.getName();
        String eTag = AwsUtil.multipartUploadWithTransferManager(BUCKET_NAME, key, file.getAbsolutePath());
        logger.info("eTag: {}", eTag);
    }

    @Test
    @Tag("bucket")
    @DisplayName("multipartUploadWithS3Client")
    public void multipartUploadWithS3Client() {
        File file = new File("D:\\Downloads\\ideaIU-2023.3.6.exe");
        String key = file.getName();
        boolean isMultipartUploadSuccessful = AwsUtil.multipartUploadWithS3Client(BUCKET_NAME, key, file.getAbsolutePath());
        logger.info("isMultipartUploadSuccessful: {}", isMultipartUploadSuccessful);
    }

    @Test
    @Tag("bucket")
    @DisplayName("downloadObjectsToDirectory")
    public void downloadObjectsToDirectory() {
        String path = "D:\\Downloads\\test";
        File file = new File(path);
        Util.mkdirParents(file);
        int failedTransfers = AwsUtil.downloadObjectsToDirectory(BUCKET_NAME, path);
        logger.info("failedTransfers: {}", failedTransfers);
    }

    @Test
    @Tag("bucket")
    @DisplayName("uploadDirectory")
    public void uploadDirectory() {
        String path = "D:\\Downloads\\highlight";
        String tempPath = "D:\\Downloads\\temp";
        //如果不需要上传到其他目录下，只需要上传到存储桶根目录，则uploadPath = tempPath
        String uploadPath = tempPath + "\\key1\\key2";
        int failedTransfers = AwsUtil.uploadDirectory(BUCKET_NAME, path, tempPath, uploadPath);
        logger.info("failedTransfers: {}", failedTransfers);
    }

    @Test
    @Tag("bucket")
    @DisplayName("deleteBucketObjects")
    public void deleteBucketObjects() {
        List<String> keys = new ArrayList<>();
        keys.add("1712678395550.png");
        keys.add("test/s3-api.pdf");
        AwsUtil.deleteBucketObjects(BUCKET_NAME, keys);
    }

    @Test
    @Tag("bucket")
    @DisplayName("getObjectVersion")
    public void getObjectVersion() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
        String key = "highlight.js-11.9.0.tar.gz";
        List<ObjectVersion> versionList = AwsUtil.getObjectVersion(BUCKET_NAME, key);
        for (ObjectVersion version : versionList){
            logger.info("key: {}", version.key());
            logger.info("versionId: {}", version.versionId());
            logger.info("isLatest: {}", version.isLatest());
            LocalDateTime lastModified = version.lastModified().atZone(ZoneId.systemDefault()).toLocalDateTime();
            logger.info("lastModified: {}", dateTimeFormatter.format(lastModified));
            logger.info("size: {}", version.size());
            logger.info("eTag: {}", version.eTag());
        }
    }

    @Test
    @Tag("bucket")
    @DisplayName("getBucketVersioningStatus")
    public void getBucketVersioningStatus() {
        String status = AwsUtil.getBucketVersioningStatus(BUCKET_NAME);
        logger.info("status: {}", status);
    }
}
